
#include "animation.h"
#include "resourcemanager.h"
#include "gamemanager.h"

FrameAnimation::FrameAnimation(void): 
	frameRate(0)
	, frameIndex(0)
	, isLoop(true)
	, paused(false)
	, finished(false)
	, frameCount(0)
	,elapsedTime(0)
	, frameRateFactor(1) {

}

FrameAnimation::~FrameAnimation(void){
}

void FrameAnimation::set(const string& animKey, float rate, const vector<string>& frames) {
	key = animKey;
	_frames.clear();
	_frames = frames;

	frameCount = frames.size();
	frameRate = rate;

	frameIndex = 0;
	elapsedTime = 0;
	
	finished = false;
	isLoop = true;
	paused = false;
	
	frameRateFactor = 1;

	setFrame(0);
}

void FrameAnimation::setFrame(int index){
	if(!_frames.empty() && index >= 0 && index < (int)_frames.size()) {
		setDisplayFrame(CREATE_SPRITEFRAME(_frames[index].c_str()));
		if(frameIndex != index) {
			frameIndex = index;
		}
	}
}

void FrameAnimation::setLogicPosition(const Point& pos) {
    _logicPosition = pos;
    setPosition(SCALE_PT(pos));
}

void FrameAnimation::update (float ticks) {
	if (paused || frameCount == 1 || (!isLoop && finished))
		return;

	float num = frameRate * frameRateFactor;
	elapsedTime += ticks;
	if (elapsedTime < num)
		return;

	int n = static_cast<int>(elapsedTime / num);
	elapsedTime -= num * n;
	frameIndex += n;

	if (frameIndex >= frameCount) {
		if (!isLoop) {
			finished = true;
		} else {
			frameIndex = 0;
		}
	}

	setFrame(frameIndex);
}

AnimationSequence::AnimationSequence(int id) : 
	id(id)
	, playingAnimIndex(0)
	, _timeElapsed(0.0f)
	, parent(nullptr) {
}

AnimationSequence::~AnimationSequence() {
	for(FrameAnimation* item : _arrAnims) {
		item->removeFromParent();
	}
	
	_arrAnims.clear();
}

bool AnimationSequence::isFinished() {
	return playingAnimIndex >= (int)_arrAnims.size();
}

void AnimationSequence::playFirst() {
	if(!_arrAnims.empty()) {
		playingAnimIndex = 0;
		FrameAnimation* anim = _arrAnims[playingAnimIndex];

		int zorder = 0;
		parent->addChild(_arrAnims[playingAnimIndex], zorder, anim->getTag());
	} else {

	}
}

void AnimationSequence::playNext() {
	playingAnimIndex++;

	if(playingAnimIndex < (int)_arrAnims.size()) {
		FrameAnimation* anim = _arrAnims[playingAnimIndex];

		int zorder = 0;
		parent->addChild(anim, zorder, anim->getTag());
	} else {

	}

	_timeElapsed = 0;
}

void AnimationSequence::update(float ticks) {
	if(playingAnimIndex < (int)_arrAnims.size()) {
		FrameAnimation* anim = _arrAnims[playingAnimIndex];
		if(anim) {
			if(anim->finished || _timeElapsed > _arrDurationss[playingAnimIndex]) {
				anim->removeFromParent();
				_arrAnims[playingAnimIndex] = nullptr;

				playNext();
			} else {
				anim->update(ticks);

				if(_arrLoops[playingAnimIndex]) {
					_timeElapsed += ticks;
				}
			}
		}
	}
}

void AnimationSequence::add(FrameAnimation* anim, bool needLoop, float duration) {
	anim->isLoop = needLoop;

	_arrAnims.push_back(anim);
	_arrLoops.push_back(needLoop);
	_arrDurationss.push_back(duration);
}
